package com.antgroup.seckill.business.common.config;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

public class ShoeShelfAllocation {

    // 定义鞋子位置的类
    public static class Position {
        int rackNumber;  // 货架编号
        int levelNumber; // 层数编号
        int positionNumber; // 位置编号

        public Position(int rackNumber, int levelNumber, int positionNumber) {
            this.rackNumber = rackNumber;
            this.levelNumber = levelNumber;
            this.positionNumber = positionNumber;
        }

        @Override
        public String toString() {
            return "货架: " + rackNumber + ", 层数: " + levelNumber + ", 位置: " + positionNumber;
        }
    }

    // 定义货架类
    public static class Rack {
        int rackNumber;  // 货架编号
        int levelsCount; // 层数
        int positionsPerLevel; // 每层的位置数量
        int[][] levels; // 层数和每层的位置数组

        public Rack(int rackNumber, int levelsCount, int positionsPerLevel) {
            this.rackNumber = rackNumber;
            this.levelsCount = levelsCount;
            this.positionsPerLevel = positionsPerLevel;
            this.levels = new int[levelsCount][positionsPerLevel];
        }

        // 添加 getRackNumber 方法
        public int getRackNumber() {
            return rackNumber;
        }

        // 分配鞋子到当前货架的方法
        public List<Position> allocateShoes(int shoeCount) {
            List<Position> allocatedPositions = new ArrayList<>();
            for (int level = 0; level < levelsCount; level++) { // 从顶层开始向下分配
                for (int pos = 0; pos < positionsPerLevel; pos++) { // 从第一个位置开始分配
                    if (levels[level][pos] == 0) { // 如果位置空闲
                        levels[level][pos] = 1; // 占用该位置
                        allocatedPositions.add(new Position(rackNumber, level + 1, pos + 1));
                        shoeCount--;
                        if (shoeCount == 0) {
                            return allocatedPositions; // 如果鞋子分配完毕，返回结果
                        }
                    }
                }
            }
            return allocatedPositions; // 如果货架位置不够，返回当前已分配的位置
        }

        // 获取当前货架空闲位置的数量
        public int getFreePositions() {
            int count = 0;
            for (int[] level : levels) {
                for (int pos : level) {
                    if (pos == 0) count++;
                }
            }
            return count;
        }
    }

    // 按照优先级顺序将鞋子分配到货架上
    public static List<Position> allocateShoesToRacks(int shoeCount, List<Rack> racks) {
        // 找出所有空闲位置大于零的货架
        List<Rack> freeRacks = racks.stream()
                .filter(rack -> rack.getFreePositions() > 0)
                .sorted(Comparator.comparingInt(Rack::getFreePositions).reversed())
                .collect(Collectors.toList());

        freeRacks.sort(Comparator.comparingInt(Rack::getRackNumber)); // 按货架编号从小到大排序

        List<Position> allAllocatedPositions = new ArrayList<>(); // 存储所有分配的位置

        for (Rack rack : freeRacks) {
            if (shoeCount == 0) break; // 如果所有鞋子都分配完了，结束循环
            int freePositions = rack.getFreePositions();
            if (freePositions > 0) { // 检查该货架是否有空闲位置
                List<Position> allocatedPositions = rack.allocateShoes(Math.min(shoeCount, freePositions)); // 如果有，开始分配鞋子
                allAllocatedPositions.addAll(allocatedPositions);
                shoeCount -= allocatedPositions.size(); // 更新剩余需要分配的鞋子数量
            }
        }

        // 如果所有货架都分配完了，仍然有剩余的鞋子数
        if (shoeCount > 0) {
            System.out.println("未能成功分配的鞋子数量: " + shoeCount);
        }

        return allAllocatedPositions; // 返回所有已分配的位置
    }

    public static void main(String[] args) {
        // 获取代码执行开始时间
        long startTime = System.currentTimeMillis();
        // 初始化货架
        int numberOfRacks = 5; // 货架数量
        int levelsPerRack = 5; // 每个货架的层数
        int positionsPerLevel = 8; // 每层的位置数量

        List<Rack> racks = new ArrayList<>();
        for (int i = 1; i <= numberOfRacks; i++) {
            racks.add(new Rack(i, levelsPerRack, positionsPerLevel));
        }

        // 模拟货架被占用的情况
        // 模拟3货架第3层，第1个位置，第2个位置，第8个位置被占用
        racks.get(2).levels[2][0] = 1;
        racks.get(2).levels[2][1] = 1;
        racks.get(2).levels[2][7] = 1;

        // 模拟2货架第2层，第1个位置，第6个位置，第8个位置被占用
        racks.get(1).levels[1][0] = 1;
        racks.get(1).levels[1][5] = 1;
        racks.get(1).levels[1][7] = 1;

        // 模拟1货架第2层，第2个位置，第5个位置，第8个位置被占用
        racks.get(0).levels[1][1] = 1;
        racks.get(0).levels[1][4] = 1;
        racks.get(0).levels[1][7] = 1;

        // 模拟1货架第1层，第1个位置，第6个位置，第7个位置，第8个位置被占用
        racks.get(0).levels[0][0] = 1;
        racks.get(0).levels[0][5] = 1;
        racks.get(0).levels[0][6] = 1;
        racks.get(0).levels[0][7] = 1;

        // 为订单中的鞋子分配位置
        // 取出订单中鞋子数量，假设这个订单中有200双鞋子
        int shoeCount = 300;


        List<Position> allocatedPositions = allocateShoesToRacks(shoeCount, racks);

        // 获取代码执行结束时间
        long endTime = System.currentTimeMillis();


        // 打印分配结果
        if (allocatedPositions.isEmpty()) {
            System.out.println("未能成功分配鞋子到货架上。");
        } else {
            for (Position pos : allocatedPositions) {
                System.out.println(pos);
            }
            // 计算并打印代码执行的总时间
            long executionTime = endTime - startTime;
            System.out.println("代码执行时间: " + executionTime + " 毫秒");
        }
    }
}